docs(teams): accurate setup wizard + env + Graph permissions#212
Merged
Conversation
The Connect Microsoft Teams wizard's instructions, credential form,
and post-validation panel previously omitted everything that turns a
real-world Teams setup into a working Beever Atlas connection:
• The App Type field placeholder was "MultiTenant", which produces
an MSAL `missing_tenant_id_error` against any tenant-scoped Azure
Bot. SingleTenant is the supported path, but nothing in the UI
said so.
• No mention of the Microsoft Graph `Channel.ReadBasic.All`
application permission required for the Graph-based channel
enumeration introduced in #206 — and no warning that ONLY a
Global Administrator can consent it (Application Administrator
and Cloud Application Administrator both return
`Authorization_RequestDenied`).
• No mention of the messaging endpoint format — users were left
guessing whether it's `/api/messages`, `/api/teams`, or
`/api/webhooks/teams`. The bot listens on `/api/teams` (see
`bot/src/index.ts:422`).
• No mention of ngrok for local dev, despite the bot needing a
publicly reachable HTTPS endpoint to receive Bot Framework
activities.
• No mention of installing the Teams app package
(`bot/teams-app/beever-atlas-teams.zip`) — without that step
the bot never appears in the team.
This change:
1. Rewrites `TEAMS_INSTRUCTIONS` (8 numbered steps with sub-bullets
for non-obvious details, ngrok callout, admin-consent gotcha,
and the .zip install path).
2. Extends `CredentialField` with optional `enum`, `default`, and
`hint` so `app_type` renders as a `<select>` (SingleTenant /
MultiTenant) defaulting to SingleTenant and the
`app_tenant_id` field carries a "why required" hint. No
regression for the other four platforms — none of them use the
new fields.
3. Replaces the generic Teams branch of `StepWebhookMode` with a
dedicated `TeamsWebhookMode` panel covering the three concrete
post-validation steps (endpoint URL, Graph permission, Teams
app package).
4. Fixes `bot/README.md` env table to include
`TEAMS_APP_TENANT_ID` and explain SingleTenant vs MultiTenant.
5. Fixes `docs/content/getting-started/teams-setup.mdx` env var
names (the doc previously referenced `TEAMS_TENANT_ID` /
`TEAMS_CLIENT_ID` / `TEAMS_CLIENT_SECRET`, which are not read
by the bot) and replaces the historical Graph permissions
table with the actually-required `Channel.ReadBasic.All`
(RSC permissions live in the manifest now).
Verified:
- `npx tsc --noEmit` clean
- `npx eslint` on `ConnectionWizard.tsx` clean
- Verifier agent confirmed: credential field key round-trip
(snake → camel) intact, no regression for slack/discord/
telegram/mattermost CREDENTIAL_FIELDS entries, `<select>` state
persists across step navigation.
Stacked on top of #206 because the wizard text describes the Graph
channel enumeration introduced there (`TeamsBridge.listChannels`'s
call to `teams.channels.list`). Retarget to `main` once #206 lands.
Confidence: high
Scope-risk: narrow — UI text + one optional schema extension; no
backend or bot code paths touched.
Directive: keep the `app_type` enum values in lockstep with the
Chat SDK adapter's `createTeamsAdapter` accepted values. The
adapter treats anything other than literal "MultiTenant" as
SingleTenant — so a typo here doesn't fail loudly, it fails
silently as a missing-tenant-id MSAL error.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First pass turned every step into a paragraph with parenthetical
rationale and warning callouts; the result rendered as a vertical
wall of prose, monospace sub-bullets full of long sentences, and a
3-card post-validation panel that re-stated info from the setup
list. User feedback: "UX is bad."
This trim:
• Reduces setup from 8 long steps to 6 single-line imperatives.
Each step says WHAT to click; rationale ("required so MSAL
client_credentials can mint the Graph token") is removed —
users don't need that to follow the click path.
• Reserves the `details` slot (monospace) for things that should
actually be monospaced: an enum value, a permission name.
Prose details made the layout feel like a code listing.
• Moves the messaging endpoint, ngrok instructions, and Teams
app `.zip` install OUT of setup and INTO the post-validation
`TeamsWebhookMode` panel — they happen AFTER credentials
validate, so putting them in the upfront list both bloated
setup and skipped the natural workflow break.
• Drops the redundant Channel.ReadBasic.All card from
TeamsWebhookMode — it's already in setup step 6, and
repeating it implied "do this again" rather than "review."
• TeamsWebhookMode is now 2 cards instead of 3, with shorter
body copy.
Verified:
- `npx tsc --noEmit` on `web/` clean
- Web image rebuilt and deployed; localhost:3000 returns HTTP 200
- The instruction list now scrolls minimally above the Display
Name input
Confidence: high
Scope-risk: narrow — UI text only.
Directive: the `details` array on a setup-step instruction renders
in monospace. Use it for code-shaped values (paths, enum values,
command snippets), NEVER for prose explanations.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…es supported
User-reported gaps after the first trim:
• The setup steps explained creds/Azure but never told users
HOW to get a public webhook URL (ngrok) or WHERE to enter the
bot URL — they were left guessing whether we needed it as a
wizard field. We don't (bot listens on a fixed path), but the
setup list must say so.
• The App Type hint read as "we only support SingleTenant" when
in fact the select offers both and the SDK accepts either.
Changes:
• Setup step 2 (new): "Expose this bridge over HTTPS, then set
the Bot's Messaging endpoint to your URL + /api/teams" with
mono details for `ngrok http 3001` and the URL pattern. This
surfaces what was previously buried in the post-validation
panel.
• Setup step 1 detail updated to "SingleTenant (recommended) or
MultiTenant" so the choice is visible upfront.
• App Type hint rewritten to lead with "Both modes are
supported" — no longer reads as a restriction.
• TeamsWebhookMode collapses from 2 cards to 1: just the .zip
app install. The endpoint card moved to the setup list above;
keeping it here would have been redundant.
Verified:
- `npx tsc --noEmit` on `web/` clean
- Web image rebuilt and deployed
Confidence: high
Scope-risk: narrow — wizard text only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…UID checks The wizard's Validate step previously only constructed the Teams adapter (format check) — a typo'd App ID or wrong secret passed "validation" and only failed later when channel enumeration silently returned []. Now: - bridge.ts handleValidateAdapter actually mints a Graph token via MSAL and classifies AADSTS / unauthorized_client / invalid_client errors as credential failures; non-auth probe failures (403 consent, network) soft-accept with a pointer to Channel.ReadBasic.All admin consent. - ConnectionWizard validates App ID / Tenant ID against the AAD GUID shape client-side, renders inline errors, and gates the Validate button until they pass. - Teams is no longer treated as webhook-only: the Channels step renders the real Graph-enumerated channel list (depends on #206). Verified live: a real Teams connection was created through this exact flow today (channel discovery + message history sync working). Constraint: validation must not require the messaging endpoint to be live yet Rejected: server-side-only GUID validation | users deserve inline feedback before a round-trip Confidence: high Scope-risk: narrow Not-tested: MultiTenant validation path against a real multi-org token Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… filename The loose manifest.json referenced botId eefc03cb-… which does not exist in any Azure tenant (stale id from an early registration attempt), and was missing webApplicationInfo + RSC permissions — a package built from it could install but never read channel history. The actual working package (built via teams CLI) used the correct id but generic "Developer/example.com" branding. Merge the two: correct id (fb24e83f-…), manifest schema 1.25, RSC perms (ChannelMessage.Read.Group, ChatMessage.Read.Chat), personal tabs, and Beever AI branding. Bump to 1.0.3 (dev portal auto-bumped to the same). build-package.mjs now writes beever-atlas-teams.zip (the name actually used/uploaded everywhere) instead of beever-atlas-bot.zip; .gitignore updated to match so the build artifact stays untracked. Constraint: dev-portal catalog already at version 1.0.2 — local manifest must be ≥1.0.3 Rejected: tracking the built zip in git | reproducible artifact, build script exists for that Confidence: high Scope-risk: narrow Directive: botId must equal the AAD app id fb24e83f-… — never regenerate it independently Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The Connect Microsoft Teams wizard had multiple silent traps that took an internal user (Alan) a full real onboarding cycle and a stack of session memory to work through. Each had a specific failure mode:
What
Behavior change